package com.hmjk.health.background.data;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Intent;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.format.Time;
import android.util.Log;

import com.hmjk.health.HealthApp;
import com.hmjk.health.background.DataManager;
import com.hmjk.health.background.NetService;
import com.hmjk.health.util.DEV_FACE;

public class DeviceFaceUpdated extends DataUpdated{
	private static String TAG = DeviceFaceUpdated.class.getSimpleName();
	private ArrayList<String> mTIDArray = new ArrayList<String>();
	private int index = 0;
	private HashMap<String, DEV_FACE> mFaceMap = new HashMap<String, DEV_FACE>();
	private boolean working = false;
	private boolean doSingle = false;
	
	private void logd(String info){
		Log.d(TAG, info);
	}
	

	public DeviceFaceUpdated(HealthApp app, DataManager dm, DataUpdated base) {
		super(app, dm, base);
		UPDATE_TIME = 2 * 60 * 60 * 1000;
		mBaseData.setNotifer(DataManager.F_DEVICEFACE,this);
	}

	@Override
	public void setUserData(Object data){
		logd("setUserData");
		reqTime = 0;
		upTime = 0;
	}
	
	private void loadBitmap(DEV_FACE d){
		InputStream bmpIs = null;
		try{
			Uri imageUri = Uri.parse("file://" + d.path);
			d.recycle();
			logd("DEV_FACE loadBitmap "+d.tid);
			bmpIs = mApp.getContentResolver().openInputStream(imageUri);
			
			d.bitmap = BitmapFactory.decodeStream(bmpIs);
			bmpIs.close();
		}catch(FileNotFoundException e){
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	public long delay() {
		long curMs = System.currentTimeMillis();
		long del = curMs - upTime;
		logd("delay curMs="+curMs+" upTime="+upTime+" del="+del);
		if(del >= UPDATE_TIME){
			logd("delay 0");
			return 0;
		}else{
			logd("delay (UPDATE_TIME - del) = "+(UPDATE_TIME - del));
			return (UPDATE_TIME - del);
		}
	}
	
	private boolean checkFace(String uid, String tid){
		DEV_FACE d = mFaceMap.get(tid);
		if(d == null){
			d = new DEV_FACE();
			d.tid = tid;
			mFaceMap.put(tid, d);
		}
		
		if(d.path == null){
			d.path = mApp.getDevFaceFileName(d.tid);
		}
		
		if(d.committing){
			return false;
		}
		
		long lstamp = 0;
		if(d.path != null){
			int pos = d.path.lastIndexOf(File.separator);
			String name = d.path.substring(pos+1);
			int len = d.tid.length();
			String sstamp = name.substring(len);
			pos = sstamp.lastIndexOf(".");
			if(pos > 0){
				sstamp = sstamp.substring(0, pos);
			}
			lstamp = Long.parseLong(sstamp);
		}
		Intent si = new Intent(NetService.GET_DATA_ACTION);
		si.putExtra("sub_act", NetService.CHECK_DEVICE_FACE);
		si.putExtra("uid", uid);
		si.putExtra("vtid", tid);
		si.putExtra("vstamp", lstamp);
			
		Time t = new Time();
		t.setToNow();
		String stamp = "CHECK_DEVICE_FACE" + t.toString(); 
		si.putExtra("stamp",stamp);
		mApp.addNetHandler(stamp,mDm.getBackGroundHandler());
		mApp.startService(si);
		return true;
	}

	private void download(String tid){
		String downfilePath = mApp.getDownloadFaceFolder();
		downfilePath += "/" + tid + ".jpg";
		
		Intent si = new Intent(NetService.DOWNLOAD_ACTION);
		si.putExtra("sub_act", NetService.DOWNLOAD_DEVICE_FACE);
		si.putExtra("tid", tid);
		si.putExtra("type", "m");
		si.putExtra("path", downfilePath);
		
		Time t = new Time();
		t.setToNow();
		String stamp = "DOWNLOAD_DEVICE_FACE" + t.toString(); 
		si.putExtra("stamp",stamp);
		mApp.addNetHandler(stamp,mDm.getBackGroundHandler());
		mApp.startService(si);
	}
	
	private void getTids(){
		JSONObject json = (JSONObject) mBaseData.check(null);
		
		mTIDArray.clear();
		if(json != null){
			try {
				JSONArray ar = json.getJSONArray("array");
				int len = ar.length();
				for(int i = 0; i < len; i++){
					JSONObject e = ar.getJSONObject(i);
					String tid = e.getString("tid");
					if((tid != null) && (tid.trim().isEmpty() == false)){
						mTIDArray.add(tid);
					}
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
	
	private void doNextRequest(){
		if(doSingle){
			doSingle = false;
			working = false;
			return;
		}
		
		String uid = mApp.getUID();
		if(uid == null){
			Log.e(TAG, "doNextRequest uid == null stoped!");
			working = false;
		}
		int size = mTIDArray.size();
		
		if(index < size){
			while(index < size){
				String tid = mTIDArray.get(index);
				if(checkFace(uid,tid)){
					index ++;
					break;
				}else{
					index ++;
				}
			}
			if(index >= size)
				working = false;
		}else{
			working = false;
		}
	}
	
	private void doRequest(String uid){
		getTids();
		int size = mTIDArray.size();
		logd("doRequest:size="+size);
		doSingle = false;
		if(size > 0){
			index = 0;
			String tid = mTIDArray.get(index);
			working = true;
			boolean ok = false;
			if(checkFace(uid,tid)){
				index ++;
			}else{
				index ++;
				doNextRequest();
			}
		}else{
			Intent i = new Intent(DataManager.DATA_UPDATE_ACTION);
			i.putExtra("type",DataManager.F_DEVICEFACE);
			i.putExtra("state", false);
			i.putExtra("tid", "");
			mApp.sendBroadcast(i);
		}
	}
	
	private void doSingleRequest(String uid, String tid){
		working = true;
		doSingle = true;
		checkFace(uid,tid);
	}
	
	@Override
	public boolean grab() {
		String uid = mApp.getUID();
		logd("grab uid="+uid);
		if(uid == null)
			return false;
		
		if(working){
			logd("grab working now");
			return false;
		}
		
		long curMs = System.currentTimeMillis();
		logd("grab curMs="+curMs+" reqTime="+reqTime);
		if((curMs - reqTime) > UPDATE_TIME){
			doRequest(uid);
			reqTime = curMs;
			logd("grab req sent!");
			return true;
		}
		return false;
	}
	
	@Override
	public boolean grabByUserWithSingleArgs(Object args){
		if(args == null)
			return false;
		
		String argString = (String) args;
		
		if(argString.trim().isEmpty())
			return false;
		
		String uid = mApp.getUID();
		logd("grabByUserWithSingleArgs uid="+uid);
		if(uid == null)
			return false;
		
		if(working){
			logd("grabByUserWithSingleArgs downloading");
			return false;
		}
				
		long curMs = System.currentTimeMillis();
		logd("grabByUserWithSingleArgs curMs="+curMs+" reqTime="+reqTime);
		if((curMs - reqTime) > 10 * 1000){
			doSingleRequest(uid, argString);
			reqTime = curMs;
			logd("grabByUserWithSingleArgs req sent!");
			return true;
		}
		return false;
	}

	@Override
	public boolean grabByUser() {
		String uid = mApp.getUID();
		logd("grabByUser uid="+uid);
		if(uid == null)
			return false;
		
		if(working){
			logd("grabByUser downloading");
			return false;
		}
		
		long curMs = System.currentTimeMillis();
		logd("grabByUser curMs="+curMs+" reqTime="+reqTime);
		if((curMs - reqTime) > 30 * 1000){
			doRequest(uid);
			reqTime = curMs;
			logd("grabByUser req sent!");
			return true;
		}
		return false;
	}

	@Override
	public void receive(String stamp, String sjson) {
		if(stamp.startsWith("CHECK_DEVICE_FACE")){
			if(sjson != null){
				boolean update = false;
				String validtid = "";
				try {
					JSONObject json = new JSONObject(sjson);
					int code = json.getInt("code");
					if(code == 200){
						String state = json.getString("state");
						JSONObject sd = json.getJSONObject("senddata");
						validtid = sd.getString("validtid");
						if(state.equalsIgnoreCase("00")){
							update = false;
							upTime = System.currentTimeMillis();
						}else if(state.equalsIgnoreCase("22")){
							update = true;
						}else{
							Log.e(TAG, "receive error state:"+state+" from network");
						}
					}
				}catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				
				if(update == false){
					doNextRequest();
					Intent i = new Intent(DataManager.DATA_UPDATE_ACTION);
					i.putExtra("type",DataManager.F_DEVICEFACE);
					i.putExtra("state", update);
					i.putExtra("tid", validtid);
					mApp.sendBroadcast(i);
				}else{
					download(validtid);
				}	
			}
		}else if(stamp.startsWith("DOWNLOAD_DEVICE_FACE")){
			if(sjson != null){
				boolean update = false;
				String tid = "";
				try {
					JSONObject json = new JSONObject(sjson);
					int code = json.getInt("code");
					if(code == 200){
						String state = json.getString("state");
						if(state.equalsIgnoreCase("00")){
							JSONObject sd = json.getJSONObject("senddata");
							JSONObject recdata = json.getJSONObject("recdata");
							if(sd != null){
								tid = sd.getString("tid");
								clearCurrent(tid);
								if(recdata != null){
									long time = recdata.getLong("timestamp");
									String filepath = json.getString("downloadfile");
									File f = new File(filepath);
									String facePath = mApp.getDevFaceFolder() + "/" + tid + time + ".jpg";
									File faceFile = new File(facePath);
									f.renameTo(faceFile);
								}
								
							}
							upTime = System.currentTimeMillis();
							update = true;
						}
					}else{
						upTime = System.currentTimeMillis();
						update = false;
					}
				}catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				
				doNextRequest();
				Intent i = new Intent(DataManager.DATA_UPDATE_ACTION);
				i.putExtra("type",DataManager.F_DEVICEFACE);
				i.putExtra("state", update);
				i.putExtra("tid", tid);
				mApp.sendBroadcast(i);
			}
		}else if(stamp.startsWith("COMMIT_DEV_FACE")){
			if(sjson != null){
				int code = 404;
				String state = "af";
				String tid = "";
				try {
					JSONObject json = new JSONObject(sjson);
					code = json.getInt("code");
					JSONObject sd = json.getJSONObject("senddata");
					tid = sd.getString("tid");
					if(code == 200){
						state = json.getString("state");
						if(state.equalsIgnoreCase("00")){
							clearCurrent(tid);
							JSONObject recdata = json.getJSONObject("recdata");
							if(recdata != null){
								long time = recdata.getLong("facetimestamp");
								String filepath = json.getString("uploadfile");
								File f = new File(filepath);
								String facePath = mApp.getDevFaceFolder() + "/" + tid + time + ".jpg";
								File faceFile = new File(facePath);
								f.renameTo(faceFile);
							}
						}
					}
				}catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				commitDone(tid);
				Intent i = new Intent(DataManager.DATA_COMMIT_RESULT);
				i.putExtra("type",DataManager.F_DEVICEFACE);
				i.putExtra("state", state);
				i.putExtra("code", code);
				i.putExtra("tid", tid);
				mApp.sendBroadcast(i);
			}
		}
	}
	
	private void commitDone(String tid){
		DEV_FACE d = mFaceMap.get(tid);
		d.committing = false;
	}
	
	private void clearCurrent(String tid){
		DEV_FACE d = mFaceMap.get(tid);
		d.recycle();
		if(d.path == null){
			d.path = mApp.getDevFaceFileName(d.tid);
		}
		if(d.path != null){
			File f = new File(d.path);
			if(f.exists())
				f.delete();
		}
		
		d.path = null;
	}

	@Override
	public Object check(String[] arg) {
		logd("DEV_FACE check");
		getTids();
		if(mTIDArray.size() > 0){
			if(arg == null){
			for(String tid:mTIDArray){
				DEV_FACE d = mFaceMap.get(tid);
				if(d == null){
					d = new DEV_FACE();
					d.tid = tid;
					mFaceMap.put(tid, d);
				}
				logd("DEV_FACE check "+d.tid);
				if(d.path == null){
					d.path = mApp.getDevFaceFileName(d.tid);
				}
				if(d.path == null){
					d.recycle();
				}else{
					if(d.bitmap == null){
						loadBitmap(d);
					}
				}
			}
			
			return mFaceMap;
			}else if((arg.length == 1) && (arg[0] != null) && (arg[0].trim().length() > 0)){
				String tid = arg[0];
				DEV_FACE f = mFaceMap.get(tid);
				if(f == null){
					f = new DEV_FACE();
					f.tid = tid;
					mFaceMap.put(tid, f);
				}
				if(f != null){
					logd("DEV_FACE check "+tid);
					if(f.path == null){
						f.path = mApp.getDevFaceFileName(f.tid);
					}
					if(f.path == null){
						f.recycle();
					}else{
						if(f.bitmap == null){
							loadBitmap(f);
						}
					}
				}
				return f;
			}
		}
		return null;
	}
	
	@Override
	public boolean commit(Object data) {
		
		try {
			JSONObject json = (JSONObject) data;
			String path = json.getString("path");
			String tid = json.getString("tid");
			
			DEV_FACE d = mFaceMap.get(tid);
			if(d == null){
				d = new DEV_FACE();
				d.tid = tid;
				mFaceMap.put(tid, d);
			}
			
			String uid = mApp.getUID();
			
			if((uid == null) || uid.isEmpty())
				return false;
			
			if((tid == null) || tid.isEmpty())
				return false;
			
			if((path == null) || (path.trim().length() == 0))
				return false;
			
			File f = new File(path);
			if(f.exists()){
				Intent si = new Intent(NetService.COMMIT_DATA_ACTION);
				si.putExtra("sub_act", NetService.COMMIT_DEV_FACE);
				si.putExtra("uid", uid);
				si.putExtra("tid", tid);
				si.putExtra("path", path);
				Time t = new Time();
				t.setToNow();
				String stamp = "COMMIT_DEV_FACE" + t.toString(); 
				si.putExtra("stamp",stamp);
				mApp.addNetHandler(stamp,mDm.getBackGroundHandler());
				mApp.startService(si);
				
				d.committing = true;
				return true;
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return false;
	}

	@Override
	public void release() {
		if(mFaceMap.isEmpty())
			return;
		
		Set<String> keys = mFaceMap.keySet();
		for(String k:keys){
			DEV_FACE f = mFaceMap.get(k);
			if(f != null)
				f.clear();
		}
		mFaceMap.clear();
	}
}
